Lambda@Edge の設置によって出力されるログは2種類ある
こんにちは、なおにしです。
Lambda@Edgeのログ出力を検証している際、出力されるログについて調査したのでご紹介します。
はじめに
Lambda@Edge のログ出力先についてはドキュメントに以下のとおり記載があります。
Lambda@Edge は、関数ログを CloudWatch Logs に自動的に送信し、関数が実行される AWS リージョン にログストリームを作成します。
つまり、CloudFront にデプロイされたLambda(Lambda@Edge)が実行された地域(エッジロケーション)に該当するリージョンにログが出力される挙動となります。
こちらの挙動については弊社ブログでも以下のとおり既に取り上げられています。
しかし、上記ブログを見ていただくとそれぞれ対象としているロググループ名が異なることが分かります。
-
/aws/lambda/us-east-1.function-name
-
/aws/cloudfront/LambdaEdge/DistributionId
どちらともLambda@Edge を使用した際に出力されるログですが、用途が異なります。
Lambda@Edge の実行ログ
1つ目のログは実際にLambda@Edgeが特定のエッジロケーションで正常に実行されることで、コード内で定義されているログ出力イベントに基づいて出力されるものです。
例えばNode.js であれば、以下のようにconsoleオブジェクトで定義されたログ文字列が各リージョンの/aws/lambda/us-east-1.function-name
に出力されます。
exports.handler = async function(event, context) {
console.log("ENVIRONMENT VARIABLES\n" + JSON.stringify(process.env, null, 2))
console.info("EVENT\n" + JSON.stringify(event, null, 2))
console.warn("Event not processed.")
return context.logStreamName
}
CloudFront が出力するエラーログ
2つ目のログは、デプロイされたLambda@Edge がエッジロケーションで実行されようとした際、コード自体に問題があって処理に失敗することでCloudFront が出力するエラーログです。
こちらのログに関する記載は以下のとおりドキュメントにあります。
Lambda が CloudFront に無効なレスポンスを返すと、Lambda 関数が実行されるリージョンで CloudFront が CloudWatch にプッシュするログファイルに、エラーメッセージが書き込まれます。
例えば、Lambda作成時にランタイムを「Node.js 20.x」に指定した状態で上記のjsコードを実行すると、以下のとおりエラーが発生します。
"errorType": "ReferenceError",
"errorMessage": "exports is not defined in ES module scope",
これは、ESモジュール方式のファイル(.mjsファイル)に、CommonJSモジュール方式のコードを記述して実行したためです。
このような状態のままLambda@Edge としてCloudFront にデプロイを行い、アクセスがきてLambda@Edge がトリガーされた時に、エラーが/aws/cloudfront/LambdaEdge/DistributionId
に出力されます。
実際に出力されるエラー内容としては、例えば今回の検証では以下のようなログが出力されました。
- JSONの出力形式が不正な場合
ERROR Validation error: The Lambda function returned an invalid json output, parsed json should be an object type.
- ヘッダー操作が不正な場合
ERROR Validation error: Lambda function result failed validation, the function tried to delete read-only header, headerName : Transfer-Encoding.
それでは実際にLambda@Edge でログを出力させてみた結果を見ていきます。
やってみた
Lambda@Edgeとしてデプロイする関数はバージニア北部(us-east-1)リージョンで作成する必要があります。今回は「test-edge-log-output」という名前で作成しました。
作成にあたっては以下のドキュメントが参考になります。
Lambda@Edge を作成する手順については上記のとおりなので割愛しますが、共通して注意する箇所は実行ロールの設定です。
デフォルトでは以下のように[基本的な Lambda アクセス権限で新しいロールを作成]が選択されています。
上記を選択したまま作成されたロールにアタッチされるポリシーの内容は以下のとおりです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:us-east-1:AccountId:*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:us-east-1:AccountId:log-group:/aws/lambda/function-name:*"
]
}
]
}
ログ出力に関するアクションが定義されていますが、バージニア北部(us-east-1)のリージョンに対してのみ許可しています。
一方、ドキュメントに記載のとおり[AWS ポリシーテンプレートから新しいロールを作成] を選択して、ポリシーテンプレートとして[基本的な Lambda@Edge のアクセス権限 (CloudFront トリガーの場合)]を適用した場合に作成されたロールにアタッチされるポリシーの内容は以下のとおりです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:*:*:*"
]
}
]
}
全リージョンに対するログ出力が許可されています。つまり、複数リージョンに対するログ出力を行うLambda@Edge用の関数を作成する場合、上記のとおりログ出力を許可するポリシーを追加しないと/aws/lambda/us-east-1.function-name
にログが出力されないことにご注意ください。
一方、CloudFront が出力する/aws/cloudfront/LambdaEdge/DistributionId
については、Lambda@Edge 用のサービスリンクロールが使用されます。
Lambda@Edge は IAM サービスリンクロールを使用します。サービスにリンクされたロールは、サービスに直接リンクされた一意のタイプの IAM ロールです。サービスにリンクされたロールは、サービスによって事前定義されており、お客様の代わりにサービスから他の AWS サービスを呼び出す必要のあるアクセス許可がすべて含まれています。
具体的に使用されるロール名は「AWSServiceRoleForCloudFrontLogger」で、アタッチされているポリシーの内容は以下のとおりです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:log-group:/aws/cloudfront/*"
}
こちらも同様に全リージョンに対するログ出力が許可されています。私は最初Lambda@Edgeで出力されるログは全て「AWSServiceRoleForCloudFrontLogger」ロールを使用すると勘違いしていたのですが、実際はLambda で設定されたサービスロールと上記のサービスリンクロールをそれぞれ使用しており、それぞれで全リージョンに対するログ出力を許可しているという形になります。
Lambda@Edge の実行状況とログ出力はCloudFront の[テレメトリー] - [モニタリング] - [Lambda@Edge]から見ると全リージョンをまたいで確認しやすくなります。
[関数ログを表示]から各リージョンにおけるCloudWatch Logs の対象ロググループ/aws/lambda/us-east-1.function-name
に遷移できます。
例としてオレゴン(us-west-2)リージョンのCloudWatch を開くと、以下のとおり自動的にロググループが作成されていました。
まとめ
Lambda@Edge のログ出力に関して、出力されるログの種類と実行ロールについて確認しました。目的のLambda@Edge のログが見当たらない時などに本記事の内容もご確認いただければと思います。
本記事がどなたかのお役に立てれば幸いです。